package websphinx;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;


public class Matcher {

	private Vector matchActions = new Vector();
	private Vector applyActions = new Vector();

	private Element ptr = null;
	private Page page = null;
	private MatchModel model;
	private String script = null;

	public Element next = null;
	public int nextAction = 0;
	public boolean actionSucc = true;
	public Vector repeats = new Vector();
	public Vector repeatTimes = new Vector();
	public MatchElemPointer context = new MatchElemPointer();
	public Map data = new HashMap<String, Vector>();
	public StringBuffer applyResult = new StringBuffer();

	public Matcher(Page page, String script, MatchModel model) {
		this.page = page;
		this.ptr = page.getRootElement();
		this.next = ptr;
		this.model = model;
		this.script = script;
	}

	public Matcher(Page page, File file, MatchModel model) throws IOException {
		this.page = page;
		this.ptr = page.getRootElement();
		this.next = ptr;
		this.model = model;

		int size = (int) file.length();
		char[] cbuf = new char[size];
		FileReader reader = new FileReader(file);
		reader.read(cbuf, 0, size);
		this.script = new String(cbuf);

	}

	public Vector getMatchActions() {
		return matchActions;
	}

	public Vector getApplyActions() {
		return applyActions;
	}

	public MatchModel getModel() {
		return model;
	}

	public String getApplyResult() {
		return applyResult.toString();
	}

	public Map getData() {
		return data;
	}

	public Page getPage() {
		return page;
	}

	public void setPage(Page page) {
		this.page = page;
	}

	/**
	 * match all actions
	 * 
	 * @return true if all actions return true. false if any action returns
	 *         false.
	 */
	public boolean match() {
		next = page.getRootElement();
		nextAction = 0;
		actionSucc = true;
		repeats.clear();
		repeatTimes.clear();
		context.clear();
		data.clear();
		matchActions.clear();

		MatchScript matchScript = new MatchScript(script);
		matchActions = matchScript.generateActions();

		while (nextAction < matchActions.size()) {
			actionSucc = ((MatchAction) matchActions.elementAt(nextAction))
					.match(this);
			if (!actionSucc) {
				if (repeats.size() != 0) {
					nextAction = (Integer) repeats.get(repeats.size() - 1) - 1;
				} else
					return false;
			}
			nextAction++;
		}

		return true;
	}

	public boolean apply(String template) {
		next = page.getRootElement();
		nextAction = 0;
		actionSucc = true;
		repeats.clear();
		repeatTimes.clear();
		context.clear();
		applyResult.setLength(0);

		MatchScript matchScript = new MatchScript(template);
		applyActions = matchScript.generateActions();

		while (nextAction < applyActions.size()) {
			actionSucc = ((MatchAction) applyActions.elementAt(nextAction))
					.apply(this);
			if (!actionSucc) {
				if (repeats.size() != 0) {
					nextAction = (Integer) repeats.get(repeats.size() - 1) - 1;
				} else
					return false;
			}
			nextAction++;
		}

		return true;
	}

	public boolean apply(File file) throws IOException {
		int size = (int) file.length();
		char[] cbuf = new char[size];
		FileReader reader = new FileReader(file);
		reader.read(cbuf, 0, size);
		String template = new String(cbuf);

		return apply(template);
	}

	public static void main(String[] args) throws Exception {


	}

}
